package tms.view;

import javax.swing.JPanel;
import java.awt.GridLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JLabel;
import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.forms.layout.ColumnSpec;
import com.jgoodies.forms.layout.FormSpecs;
import com.jgoodies.forms.layout.RowSpec;
import javax.swing.JTable;
import javax.swing.JButton;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.JScrollPane;

import tms.controler.TravelOptionController;
import tms.model.Flight;

public class TravelOptionView extends JPanel {

    private static final long serialVersionUID = 1L;

    private JTable tblDeparture;
    private JTable tblReturn;
    private JLabel lblDepartureFrom;
    private JLabel lblReturnFrom;
    private JPanel pnlReturn;
    private JPanel pnlDeparture;

    private FlightTableModel departureTableModel;
    private FlightTableModel returnTableModel;

    private TravelOptionController controller;
    private JButton btnNext;

    /**
     * Create the panel.
     */
    public TravelOptionView(final TravelOptionController controller) {

        departureTableModel = new FlightTableModel();
        returnTableModel = new FlightTableModel();

        this.controller = controller;

        setPreferredSize(new Dimension(800, 600));
        setLayout(new GridLayout(0, 1, 0, 0));

        pnlDeparture = new JPanel();
        pnlDeparture.setFont(new Font("Tahoma", Font.PLAIN, 12));
        add(pnlDeparture);
        pnlDeparture.setLayout(new FormLayout(new ColumnSpec[] {
                FormSpecs.UNRELATED_GAP_COLSPEC,
                ColumnSpec.decode("50dlu"),
                FormSpecs.RELATED_GAP_COLSPEC,
                ColumnSpec.decode("50dlu"),
                FormSpecs.RELATED_GAP_COLSPEC,
                ColumnSpec.decode("50dlu:grow"),
                FormSpecs.UNRELATED_GAP_COLSPEC},
            new RowSpec[] {
                FormSpecs.UNRELATED_GAP_ROWSPEC,
                RowSpec.decode("22px"),
                FormSpecs.RELATED_GAP_ROWSPEC,
                RowSpec.decode("fill:default")}));

        lblDepartureFrom = Tools.createLabel("Departure from ", Tools.TAHOMA_BOLD_16);
        pnlDeparture.add(lblDepartureFrom, "2, 2, 5, 1, fill, center");

        JScrollPane scrpDeparture = new JScrollPane();
        pnlDeparture.add(scrpDeparture, "2, 4, 5, 1, fill, fill");

        tblDeparture = new JTable();
        scrpDeparture.setViewportView(tblDeparture);
        tblDeparture.setModel(departureTableModel);
        tblDeparture.getColumnModel().getColumn(4).setResizable(false);
        tblDeparture.getColumnModel().getColumn(4).setPreferredWidth(48);
        departureTableModel.addTableModelListener(new TableModelListener() {
            public void tableChanged(TableModelEvent e) {
                if (isViewDisplayed()) {
                    if (departureTableModel.getRowCount() > 0) {
                        controller.updateTicket();
                    }
                }
            }
        });
        pnlReturn = new JPanel();
        pnlReturn.setFont(Tools.TAHOMA_PLAIN_12);
        add(pnlReturn);
        pnlReturn.setLayout(new FormLayout(new ColumnSpec[] {
                FormSpecs.UNRELATED_GAP_COLSPEC,
                ColumnSpec.decode("50dlu"),
                FormSpecs.RELATED_GAP_COLSPEC,
                ColumnSpec.decode("50dlu"),
                FormSpecs.RELATED_GAP_COLSPEC,
                ColumnSpec.decode("max(157dlu;default):grow"),
                FormSpecs.UNRELATED_GAP_COLSPEC},
            new RowSpec[] {
                FormSpecs.UNRELATED_GAP_ROWSPEC,
                RowSpec.decode("22px"),
                FormSpecs.RELATED_GAP_ROWSPEC,
                RowSpec.decode("default:grow"),
                FormSpecs.RELATED_GAP_ROWSPEC,
                FormSpecs.DEFAULT_ROWSPEC,
                FormSpecs.UNRELATED_GAP_ROWSPEC}));

        lblReturnFrom = Tools.createLabel("Return from", Tools.TAHOMA_BOLD_16);
        pnlReturn.add(lblReturnFrom, "2, 2, 5, 1, fill, center");

        JScrollPane scrpReturn = new JScrollPane();
        pnlReturn.add(scrpReturn, "2, 4, 5, 1, fill, fill");

        tblReturn = new JTable();
        tblReturn.setModel(returnTableModel);
        scrpReturn.setViewportView(tblReturn);
        returnTableModel.addTableModelListener(new TableModelListener() {
            public void tableChanged(TableModelEvent e) {
                if (isViewDisplayed()) {
                    if (returnTableModel.getRowCount() > 0) {
                        controller.updateTicket();
                    }
                }
            }
        });

        btnNext = Tools.createButton("Next");
        btnNext.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                controller.moveToBookingContactInfo();
            }
        });
        pnlReturn.add(btnNext, "2, 6");
    }

    public boolean isViewDisplayed() {
        return this.isShowing();
    }

    public void addBookingSummaryPanel(SummaryPanel view) {
        assert (view != null);
        // add to the top
        add(view, 0);
    }

    public void setDepartureTableData(Object[][] data) {
        assert (data != null);
        departureTableModel.setData(data);
        if (data.length > 0) {
            departureTableModel.setValueAt(
                    Boolean.TRUE, 0, departureTableModel.getColumnCount() - 1);
            controller.updateTicket();
        }
    }

    public void setReturnTableData(Object[][] data) {
        assert (data != null);
        returnTableModel.setData(data);
        if (data.length > 0) {
            returnTableModel.setValueAt(
                    Boolean.TRUE, 0, returnTableModel.getColumnCount() - 1);
            controller.updateTicket();
        }
    }

    public Flight getSelectedDepartFlight() {
        return departureTableModel.getSelectedFlight();
    }

    public Flight getSelectedReturnFlight() {
        return returnTableModel.getSelectedFlight();
    }

    private class FlightTableModel extends AbstractTableModel {

        private static final long serialVersionUID = 1L;

        String[] columns = new String[] {
                "Depart", "Arriver", "Flight Name", "Price", "Choose"
        };
//      Object[][] data = new Object[][]{{new Flight(), Boolean.FALSE}};
        Object[][] data = new Object[][]{};

        public void setData(Object[][] data) {
            this.data = data;
        }

        public Flight getSelectedFlight() {
            int selectedRow = getSelectedRow();
            Flight selection = null;
            if (selectedRow > -1) {
                 selection = (Flight) data[selectedRow][0];
            }
            return selection;
        }

        /**
         * Get the row which is currently ticked on the CheckBox.
         */
        private int getSelectedRow() {
            int rowCount = getRowCount();
            for (int i = 0; i < rowCount; i++) {
                if (getValueAt(i, 4) == Boolean.TRUE) {
                    return i;
                }
            }
            return -1;
        }

        public int getColumnCount() {
            return columns.length;
        }

        public int getRowCount() {
            assert (data != null);
            return data.length;
        }

        public Object getValueAt(int row, int col) {
            assert (col > 0 && col < columns.length);

            Flight f = (Flight) data[row][0]; // 0 is flight
            switch(col) {
            case 0:
                return f.getDeparting();
            case 1:
                return f.getArriving();
            case 2:
                return f.getFlightName();
            case 3:
                return f.getPrice();
            default:
                return data[row][1]; // 1 is CheckBox
            }
        }

        @Override
        public void setValueAt(Object aValue, int row, int column) {
            // the last column
            if (column == (columns.length - 1)) {
                int rowCount = getRowCount();
                assert (row >= 0 && row < rowCount);
                // set all rows to unselected
                for (int i = 0; i < rowCount; i++) {
                    data[i][1] = Boolean.FALSE;
                }
                // update the current column as selected
                data[row][1] = aValue;
            }
            // reload the table
            fireTableDataChanged();
        }

        @Override
        public String getColumnName(int index) {
            return columns[index];
        }

        @SuppressWarnings("rawtypes")
        Class[] columnTypes = new Class[] {
                String.class, String.class, String.class, Double.class, Boolean.class
        };

        @SuppressWarnings({ "unchecked", "rawtypes" })
        public Class getColumnClass(int columnIndex) {
            return columnTypes[columnIndex];
        }

        boolean[] columnEditables = new boolean[] {
            false, false, false, false, true
        };

        public boolean isCellEditable(int row, int column) {
            return columnEditables[column];
        }
    }
}
